package org.misty.practices.algorithm.hanoi.normal;

import org.jetbrains.annotations.NotNull;

import java.util.*;

public class Tower implements Comparable<Tower> {
    private final Deque<Integer> stack = new ArrayDeque<>();
    private Tower next;
    public final String name;

    public Tower(String name, int level) {
        if (level < 0) {
            throw new IllegalArgumentException("level: " + level);
        }
        this.name = name;
        for (int i = level; i > 0; i--) {
            stack.push(i);
        }
    }

    public Tower(String name) {
        this(name, 0);
    }

    public String moveToNext() {
        if (this.compareTo(this.next) < 0) {
            moveTo(this.next);
            return this.name + " -> " + this.next.name;
        } else {
            throw new RuntimeException("无法从塔" + this.name + "移动到塔" + this.next.name);
        }
    }

    public Integer head() {
        if (!stack.isEmpty()) {
            return stack.peek();
        } else {
            return Integer.MAX_VALUE;
        }
    }

    public boolean isEmpty() {
        return stack.isEmpty();
    }

    public Tower getNext() {
        return next;
    }

    public void setNext(Tower next) {
        this.next = next;
    }

    public String states() {
        return stack.toString();
    }

    @Override
    public int compareTo(@NotNull Tower o) {
        int x = this.head();
        int y = o.head();
        if (x == y) return 0;
        return x > y ? 1 : -1;
    }

    private void moveTo(Tower y) {
        y.stack.push(this.stack.pop());
    }

    @Override
    public String toString() {
        return "Tower " + this.name + " " + this.stack.toString();
    }

    public static String exchange(Tower x, Tower y) {
        Objects.requireNonNull(x);
        Objects.requireNonNull(y);
        var res = x.compareTo(y);
        if (res < 0) {
            x.moveTo(y);
            return x.name + " -> " + y.name;
        } else if (res > 0) {
            y.moveTo(x);
            return y.name + " -> " + x.name;
        } else {
            throw new RuntimeException("无法从塔" + x.toString() + "移动到塔" + y.toString());
        }
    }
}
